using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

namespace Weazel.Microblaze.Simulator.Components.Microblaze.Disassembler
{
    public class Disassembler
    {
        public Instruction DisassembleInstruction(uint address, uint instruction)
        {
            try
            {
                Instruction instr =
                  Decoder.Decode((uint)(address), instruction);

                return instr;
            }
            catch (Exception)
            {
                // error in disassembly
                return null;
            }
        }

        public List<Instruction> Disassemble(uint address, byte[] bytes)
        {
            List<Instruction> instructions = new List<Instruction>();

            for (int i = 0; i < bytes.Length; i += 4)
            {
                uint instruction =
                  (uint)bytes[i + 0] << 24 |
                  (uint)bytes[i + 1] << 16 |
                  (uint)bytes[i + 2] << 8 |
                  (uint)bytes[i + 3];

                Instruction instr =
                  Decoder.Decode((uint)(i + address), instruction);

                instructions.Add(instr);
            }

            return instructions;
        }

        public void DisassembleToDisk(uint adddress, byte[] bytes, string file)
        {
            Stream stream = null;
            StreamWriter writer = null;

            try
            {
                stream = File.Open(file, FileMode.Create);
                writer = new StreamWriter(stream);

                List<Instruction> instructions = Disassemble(adddress, bytes);

                for(int i = 0; i < instructions.Count; i += 4)
                {
                    Instruction inst = instructions[i];

                    writer.WriteLine("0x{0,8:X8} (0x{1,8:X8}) {2}",
                        (adddress + i),                        
                        inst.Value,
                        inst.ToString()
                    );

                }

            }
            finally
            {
                if (writer != null)
                    writer.Close();

                if (stream != null)
                    stream.Close();
            }
        }
    }
}
